<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>WeakMap</title>
</head>
<body>
  <script>
    // WeakMap结构与Map结构类似，也是用于生成键值对的集合
    var wm1 = new WeakMap();
    var key = {foo: 1};
    wm1.set(key, 2);
    wm1.get(key); // 1

    // WeakMap也可以接受一个数组作为构造函数的参数
    var k1 = [1,2,3];
    var k2 = [4, 5, 6];
    var wm2 = new WeakMap([[k1, 'foo'], [k2, 'bar']]);
    console.log(wm2);
    /**
     * WeakMap 与 Map的区别
     * 首先，weakMap只接受对象作为键名(null除外)，不接受其他类型的值作为键名(数组也是对象的一种！)
     * 其次，WeakMap的键名所指向的对象，不计入垃圾回收机制。
     * WeakMap的设计目的在于，有时我们想在某个对象上存放一些数据，但是这会形成对于这个对象的引用。
     * 请看下面的例子
     *
    */
   var e1 = document.getElementById('foo');
   var e2 = document.getElementById('bar');
   var arr = [
     [e1, 'foo元素'],
     [e2, 'bar元素']
   ];
   /**
    * 上面代码中，e1和e2是俩个对象，我们通过arr数组对这俩个对象添加一些文字说明，
    * 这就形成了arr对e1和e2的引用。
    * 一旦不再需要这俩个对象，我们就必须手动删除这个引用，否则垃圾回收机制就不会释放e1和e2占用的内存。
   */
  arr[0] = null;
  arr[1] = null;
  /**
   * 上面这样的写法显然很不方便，一旦忘了写，就会造成内存泄漏。
   * WeakMap就是为了解决这个为而诞生的，它的键名所引用的对象都是弱引用，即垃圾回收机制不将该引用考虑在内。
   * 因此，只要所引用的对象的其他引用都被清除，垃圾回收机制就会释放该对象所占的用的内存。
   * 也就是说，一旦不再需要，WeakMap里面的键名对象和所对应的键值对会自动消失，不用手动删除引用。
   *
   * 基本上，如果你要往对象上添加数据，又不想干扰垃圾回收机制，就可以使用WeakMap。
   * 一个典型的应用场景是，在网页的DOM元素上添加数据，就可以使用WeakMap结构，当该DOM元素被清除，其所对应的WeakMap记录就会自动被移除
   * 总之，WeakMap的专用场合就是，它的键所对应的对象，可能会在将来消失。WeakMap结构有助于防止内存泄漏。
   * 注意，WeakMap 弱引用的只是键名，而不是键值。键值依然是正常引用。
  */
  var wm = new WeakMap();
var key = {};
var obj = {foo: 1};

wm.set(key, obj);
obj = null;
wm.get(key)
// Object {foo: 1}
// 上面代码中，键值obj是正常引用。所以，即使在 WeakMap 外部消除了obj的引用，WeakMap 内部的引用依然存在。
  </script>
</body>
</html>